home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-08-13 | 22.9 KB | 808 lines | [TEXT/CWIE] |
- /*************************************************************************************
- MoofWars.cp
-
- All of the main game functions are defined in here, including initialization, tear-down
- and the actual game loop.
-
- Author: Timothy Carroll
- Apple Developer Technical Support
- timc@apple.com
-
- Modification History:
-
- 4/2/97 TMC Now dispose of the color table when we exit the game. Technically,
- we still end up leaking the appPalette, so this should be corrected if InitGame is called
- more than once.
-
- 4/2/97 TMC Now check DSpStartup error code.
- 2/24/97 TMC Now conditionally allocate QD globals if we aren't using Metrowerks
- 1/23/97 TMC allocate QuickDraw globals so that MrC will compile.
- 1/23/97 TMC Added include for Moofwars.h so that MrC will compile
- 1/23/97 TMC Now include other system headers so that MrC will compile.
- 8/15/96 TMC Initial Release
-
- Copyright © 1996, 1997 Apple Computer, Inc., All Rights Reserved
-
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
-
- *************************************************************************************/
-
-
-
- #if __profile__
- #include <profiler.h>
- #endif
-
- #include <fp.h>
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <Sound.h>
-
-
- #include "Moofwars.h"
- #include "TTileGrid.h"
- #include "TSpriteCollection.h"
- #include "TShipSprite.h"
- #include "TEnemySprite.h"
- #include "TShotSprite.h"
-
- #if qShowTiming
- #include <Timer.h>
- #include <FixMath.h>
- #include <TextUtils.h>
- #endif
-
- /********************************************************************************
- GLOBALS
- ********************************************************************************/
-
- // Quickdraw Globals
- #if TARGET_RT_MAC_CFM
- #ifndef __MWERKS__
- QDGlobals qd;
- #endif
- #endif
-
- CTabHandle gAppColorTable = NULL;
- DSpContextReference gDrawContext = NULL;
-
- // We define a few static variables to hold all the game information. Only in a few cases
- // do we actually need to export this information to other functions. In general, if a
- // particular object needs a piece of information, it should be sent directly to that object,
- // rather than be imported as a global.
-
- // The playing field
- static TTileGrid *theGrid = NULL;
- WorldRect32 gWorldBounds;
-
- // All of the sprite groups
- static TSpriteCollection *gFriendlyShipGroup = NULL;
- static TSpriteCollection *gEnemyShipGroup = NULL;
- static TSpriteCollection *gFriendlyShotGroup = NULL;
- static TSpriteCollection *gEnemyShotGroup = NULL;
-
- // We keep track of the two ships separately as well,
- // as we can use them as the camera location
- static TShipSprite *gFriendlyShip = NULL;
- static TEnemySprite *gEnemyShip = NULL;
-
- // Although the sprites would load their own graphics (because of the magic of our TGraphic
- // collection, we can preload the graphics and pass them to the TSprite constructors for
- // speed. These variables will manage the loading and unloading of the sprites.
-
- TGraphicCollection *gShipGraphics = NULL;
- TGraphicCollection *gEnemyGraphics = NULL;
- TGraphicCollection *gShotGraphics = NULL;
-
- #if qUsingSound
- // Sounds
- SndReference gSounds[10];
- Boolean gPlayingSound = true; // If false, no sounds will play
- #endif
-
- #if qShowTiming
- // Miscellaneous
- long gShotsOnBoard = 0; // Holds the total number of shots in game
- #endif
-
- // Holds the current state of the keyboard and other input devices when processing
- // the list of sprites.
- TInputState gCommandKeys;
- TCommandTimer theTimer;
-
- // A standard set of lookup tables in 16.16 fixed notation, so that we can quickly
- // do sin and cos. We currently use 48 frames because thats easy to do from
- // Specular Infini-D. 360/48 = 7.5° per angle.
- SInt32 gSinLookup[48];
- SInt32 gCosLookup[48];
-
-
- /********************************************************************************
- GLOBALS
- ********************************************************************************/
-
- void main (void);
-
- // Initialize everything for the game
- static OSStatus InitGame (void);
-
- // Fills in the initial values in the lookup tables.
- static OSStatus InitAngleLookups (void);
-
- #if qUsingSound
- // Initializes Sound API and loads all the sound resources
- static OSStatus LoadSounds (void);
- #endif
-
- // This creates a draw sprocket context
- static OSStatus InitDrawSprocket (void);
-
- // This loads all of our graphics and tile resources
- static OSStatus LoadGameGraphics (void);
-
- // This creates the grid, the initial sprites and sprite groups.
- static OSStatus CreateGame (void);
-
- // The actual event loop
- static OSStatus RunGame (void);
-
- // The cleanup code for InitGame
- static OSStatus CloseGame (void);
-
-
- /********************************************************************************
- main
-
- All main does is the standard mac init, followed by initializing the game
- and running it once. In a real game it would probably put up a splash screen
- with some widgets on it.
- ********************************************************************************/
- void main (void)
- {
-
- int loop;
- OSStatus theErr = noErr;
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- MaxApplZone();
-
- for (loop = 0; loop < 30; loop++)
- MoreMasters();
-
- theErr = InitGame();
- FAIL_OSERR (theErr, "\pCouldn't initialize new game")
- theErr = RunGame();
- FAIL_OSERR (theErr, "\pFailure in game running code")
-
- error:
- cleanup:
- theErr= CloseGame();
- }
-
-
- /************************************************************************************
- InitGame
-
- Init Game loads all the sprites and sets up all the variables for running a game.
- Eventually, we can split out a large number of these routines so that they only
- need to be called when the application actually initializes, rather than once per game.
-
- Of course, our loading routines are way cool, so we may not care. :)
-
-
- ************************************************************************************/
-
- OSStatus InitGame (void)
- {
- OSStatus theErr = noErr;
- PaletteHandle appPalette;
-
- // Load our initial color table and make it the default palette for the entire application.
- // (We'll also send this color table to DrawSprocket)
-
- gAppColorTable = GetCTable (kAppColorTableResID);
- FAIL_NIL (gAppColorTable, "\pFailed to load the color table")
- appPalette = NewPalette (256, gAppColorTable, pmExplicit + pmTolerant, 0);
- FAIL_NIL (appPalette, "\pFailed to convert the color table into a palette")
- SetPalette ( (WindowRef) -1L, appPalette, false);
-
- // Initialize the sound effects
- #if qUsingSound
- theErr = LoadSounds();
- FAIL_OSERR (theErr, "\pFailed to load the sounds")
- #endif
-
- // Initialize our predefined arrays of the move angles.
- theErr = InitAngleLookups();
- FAIL_OSERR (theErr, "\pFailed to initialize the lookup tables")
-
- // Initialize the keyboard command routines.
-
- #if qSyncTiming
- theTimer.Initialize(30); // 30 frames per second
- #else
- theTimer.Initialize (0); // one command per frame, fast as possible.
- #endif
-
- // Create a draw sprocket context
- theErr = InitDrawSprocket ();
- FAIL_OSERR (theErr, "\pFailed to initialize draw sprocket")
-
- // Load the game graphics
- theErr = LoadGameGraphics();
- FAIL_OSERR (theErr, "\pFailed to preload the game graphics")
-
- // Create all of the game objects -- note that the stuff in here is probably the only thing that
- // would be run more than once every time the application runs -- the rest of the initialization code
- // will all run once.
- theErr = CreateGame();
- FAIL_OSERR (theErr, "\pFailed to create the game objects")
-
- return noErr;
-
- error:
-
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
-
- /************************************************************************************
- InitAngleLookups
-
- ************************************************************************************/
-
- OSStatus InitAngleLookups(void)
- {
- int loop;
-
- for (loop = 0; loop < 48; loop++)
- {
- double angle = (90 - loop * 7.5)/57.296;
-
- gSinLookup[loop] = (1<<14) * sin (angle);
- gCosLookup[loop] = (1<<14) * -cos (angle);
- }
-
- return noErr;
- }
-
-
- /************************************************************************************
- LoadSounds
-
- This initializes whatever sound API we're using and loads all of the sound resources.
-
- ************************************************************************************/
-
- #if qUsingSound
- OSStatus LoadSounds (void)
- {
- OSStatus theErr;
- // Initialize and load all of the game sounds.
-
- theErr = HY_Setup (kNormal, 5);
- FAIL_OSERR (theErr, "\p Failed to set up hollywood API")
- gSounds[0] = HY_GetSoundResource(6000);
- FAIL_NIL(gSounds[0], "\p Failed to allocate the sound resource")
- gSounds[1] = HY_GetSoundResource(6001);
- FAIL_NIL(gSounds[1], "\p Failed to allocate the sound resource")
- gSounds[2] = HY_GetSoundResource(6002);
- FAIL_NIL(gSounds[2], "\p Failed to allocate the sound resource")
- gSounds[3] = HY_GetSoundResource(6003);
- FAIL_NIL(gSounds[3], "\p Failed to allocate the sound resource")
- gSounds[4] = HY_GetSoundResource(6004);
- FAIL_NIL(gSounds[4], "\p Failed to allocate the sound resource")
- gSounds[5] = HY_GetSoundResource(6005);
- FAIL_NIL(gSounds[5], "\p Failed to allocate the sound resource")
-
- return noErr;
-
- error:
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
- #endif
-
-
- /************************************************************************************
- InitDrawSprocket
-
- ************************************************************************************/
- OSStatus InitDrawSprocket (void)
- {
- OSStatus theErr = noErr;
- DSpContextAttributes screenData;
- RGBColor fade;
-
- // Create a Draw Sprocket context for the screen.
- theErr = DSpStartup();
- FAIL_OSERR (theErr, "\pError: Failed to start up DrawSprocket")
-
- // fill in our requirements. Anything we place here we need to have for our game to work properly.
- screenData.frequency = 0;
- screenData.displayWidth = 640;
- screenData.displayHeight = 480;
- screenData.reserved1 = 0;
- screenData.reserved2 = 0;
- screenData.colorNeeds = kDSpColorNeeds_Require;
- screenData.colorTable = gAppColorTable;
- screenData.contextOptions = 0;
- screenData.backBufferDepthMask = kDSpDepthMask_8;
- screenData.displayDepthMask = kDSpDepthMask_8;
- screenData.backBufferBestDepth = 8;
- screenData.displayBestDepth = 8;
- screenData.pageCount = 2;
- screenData.gameMustConfirmSwitch = false;
- screenData.reserved3[0] = 0;
- screenData.reserved3[1] = 0;
- screenData.reserved3[2] = 0;
- screenData.reserved3[3] = 0;
-
- theErr = DSpUserSelectContext(&screenData, 0,NULL, &gDrawContext);
- FAIL_OSERR (theErr, "\p Failed to retrieve a drawing context")
-
- // We should now alter the screenData to reflect things that would be useful to have, but aren't
- // requirements.
-
- #if qUsePageFlip
- screenData.contextOptions |= kDSpContextOption_PageFlip;
- screenData.pageCount = 3;
- #endif
-
- #if (!qSyncToDrawVBL)
- screenData.contextOptions |= kDSpContextOption_DontSyncVBL;
- #endif
-
- // Reserve the screen and set it to active.
- theErr = DSpContext_Reserve (gDrawContext, &screenData);
- FAIL_OSERR (theErr, "\pFailed to reserve the context")
- #if 0
- theErr = DSpContext_SetMaxFrameRate (gDrawContext, 60);
- FAIL_OSERR (theErr, "\p Failed to set the maximum frame rate")
- #endif
-
- fade = kBlack; // DrawSprocket requires this to be a non-const param
-
- theErr = DSpContext_FadeGammaOut (gDrawContext, &fade);
- FAIL_OSERR (theErr, "\p Failed to fade out")
-
- theErr = DSpContext_SetState (gDrawContext, kDSpContextState_Active);
- FAIL_OSERR (theErr, "\pFailed to activate the draw context")
-
- theErr = DSpContext_FadeGammaIn (gDrawContext, &fade);
- FAIL_OSERR (theErr, "\p Failed to fade in")
-
- return noErr;
-
- error:
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
-
-
- /************************************************************************************
- LoadGameGraphics
- ************************************************************************************/
-
- OSStatus LoadGameGraphics (void)
- {
- OSStatus theErr = noErr;
- // Preload and lock all of our game's graphics so that everything runs smoothly.
-
- gShipGraphics = TGraphicCollection::NewCollection (kShipResourceID);
- FAIL_NIL (gShipGraphics, "\pcouldn't load friendly ship graphics")
- gShipGraphics->LockCollection();
-
- gShotGraphics = TGraphicCollection::NewCollection (kShotResourceID);
- FAIL_NIL (gShotGraphics, "\pcouldn't load friendly shot graphics")
- gShotGraphics->LockCollection();
-
- // This version uses the same graphics for the enemy and friendly units, but you can
- // insert your own favorite graphics instead.
- #if 0
- gEnemyGraphics = TGraphicCollection::NewCollection (kEnemyResourceID);
- FAIL_NIL (gEnemyGraphics, "\pcouldn't load enemy graphics")
- gEnemyGraphics->LockCollection();
- #endif
-
- return noErr;
-
- error:
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
-
-
- /************************************************************************************
- CreateGame
-
- ************************************************************************************/
- OSStatus CreateGame (void)
- {
- OSStatus theErr = noErr;
- Rect boundsRect = {0,0, 480, 640};
-
- TShipSpriteData shipData;
- TEnemySpriteData enemyData;
-
- // Load the Grid and Tiles. Note that we do load the tile graphics here as well --
- // we could move that to LoadGameGraphics if we wanted.
- // Load the tile grid information
- theGrid = new TTileGrid();
- theErr = theGrid->CreateGridFromResource(kGridResourceID);
- FAIL_OSERR (theErr, "\p Failed to load the grid resource")
-
- // Initialize the world boundaries in 16.16 fixed point coordinates.
-
- gWorldBounds.left = 0;
- gWorldBounds.top = 0;
- gWorldBounds.right = theGrid->GetGridWidth() * (32 << 16);
- gWorldBounds.bottom = theGrid->GetGridHeight() * (32 << 16);
-
-
- // Create groups for all of our game's sprites
-
- gFriendlyShipGroup = new TSpriteCollection ();
- FAIL_NIL (gFriendlyShipGroup, "\pcouldn't create friendly ship group")
- gEnemyShipGroup = new TSpriteCollection ();
- FAIL_NIL (gEnemyShipGroup, "\pcouldn't create enemy ship group")
- gFriendlyShotGroup = new TSpriteCollection ();
- FAIL_NIL (gFriendlyShotGroup, "\pcouldn't create friendly shot group")
- gEnemyShotGroup = new TSpriteCollection ();
- FAIL_NIL (gEnemyShotGroup, "\pcouldn't create enemy shot group")
-
-
- // Create the good guy ship
-
- shipData.spriteData.spriteType = TShipSprite::kSpriteType;
- shipData.spriteData.initialX = (100) << 16;
- shipData.spriteData.initialY = (100) << 16;
- shipData.spriteData.initialXVelocity = 0;
- shipData.spriteData.initialYVelocity = 0;
- shipData.spriteData.visibility = kVisible;
- shipData.spriteData.face = 0;
- shipData.spriteData.collectionID = 1000;
- shipData.spriteData.preloadedCollection = gShipGraphics;
- shipData.rotateInterval = 1;
- shipData.shotInterval = 1;
- shipData.shotsGroup = gFriendlyShotGroup;
-
- gFriendlyShip = new TShipSprite(&shipData);
- gFriendlyShip->AddToGroup (gFriendlyShipGroup);
-
- // Create the enemy ship
- // We are using the same graphics here, but this can be changed if you want
- // a separate villain.
- enemyData.spriteData.spriteType = TEnemySprite::kSpriteType;
- enemyData.spriteData.initialX = (1200) << 16;
- enemyData.spriteData.initialY = (1200) << 16;
- enemyData.spriteData.initialXVelocity = 0;
- enemyData.spriteData.initialYVelocity = 0;
- enemyData.spriteData.visibility = kVisible;
- enemyData.spriteData.face = 0;
- enemyData.spriteData.collectionID = 1000;
- enemyData.spriteData.preloadedCollection = gShipGraphics;
- enemyData.rotateInterval = 1;
- enemyData.shotInterval = 1;
- enemyData.shotsGroup = gEnemyShotGroup;
-
- gEnemyShip = new TEnemySprite(&enemyData);
- gEnemyShip->AddToGroup (gEnemyShipGroup);
-
- return noErr;
-
- error:
- if (theErr == noErr)
- theErr = paramErr;
- return theErr;
- }
-
-
- OSStatus RunGame (void)
- {
- // Is game currently running?
- Boolean running = true;
-
- // We need a separate boolean to determine is the sound key is still being held down -- if it is, we
- // don't toggle. Otherwise we'd keep turning the sound off and on.
- Boolean soundKeyDown = false;
-
- OSStatus theErr = noErr;
-
- //DrawSprocket will return us a CGrafPtr to draw into.
- CGrafPtr buffer;
-
- //The center of the tile grid is tracked by a camera position. In this version of the code, this
- //position is identical to the ship, but it could actually be any arbitrary point. Missile-CAM!
- SInt32 cameraX, cameraY;
- SInt32 tileTop, tileLeft;
- Rect clipping = {0,0,480,640};
-
- #if qShowTiming
- UnsignedWide startMicroSec, endMicroSec;
- Str255 theString;
- long frame;
- #endif
-
- // We play a beep to signal the start of the game.
- SysBeep(2);
- HideCursor();
- // Basic structure of the game loop is:
- // * erase all sprites
- // * draw all sprites in their new locations
- // * refresh the screen
- // * move and hit test the sprites based on any queued commands.
-
- // Erasing and drawing is relative to a clipping rectangle and a graphics scale.
- // If at all possible, keep different clipping areas in the game from overlapping.
- // failing that, do all erases in all clip areas before any sprites are drawn.
-
- // For the current version (fixed map), all scaling data is constant, so we can
- // set it once and ignore it. If we are changing the scaling data, then we need to
- // move this section into the loop. Note that scaling data will be different
- // for erases and draws in that case.
-
- // Set the initial camera location.
- gFriendlyShip->GetCurrentWorldLocation(&cameraX, &cameraY);
-
- #if __profile__
- ProfilerInit(collectDetailed, PPCTimeBase, 200, 30);
- #endif
-
- #if qShowTiming
- Microseconds(&startMicroSec);
- #endif
-
- #if qSyncTiming
- theTimer.AcceptCommands(true);
- #endif
-
- while (running)
- {
- /************* Point at the Current Buffer ***************************/
- theErr = DSpContext_GetBackBuffer( gDrawContext,kDSpBufferKind_Normal, &buffer );
- #if qDebugging
- FAIL_OSERR(theErr, "\p Failed to retrieve a drawing surface.")
- #endif
-
- SetPort ((GrafPtr) buffer);
- SetDestinationBuffer (buffer->portPixMap, NULL);
-
- /************* Set the camera location ***************************/
-
- gFriendlyShip->GetCurrentWorldLocation(&cameraX, &cameraY);
-
- SetBufferClip (&clipping);
- SetWorldOrigin(cameraX, cameraY);
-
-
- /************* Draw the Tile Grid ************************/
- tileLeft = (cameraX >> 16) - 320;
- tileTop = (cameraY >> 16) - 240;
-
- theGrid->DrawGrid (&clipping, tileTop,tileLeft);
-
- /************** Show the time to draw the current frame *******/
- #if qShowTiming
- Microseconds(&endMicroSec);
- WideSubtract((wide *) &endMicroSec, (wide *) &startMicroSec);
- Microseconds(&startMicroSec); // start timing the next frame
- frame = 1000000.0/endMicroSec.lo;
-
- RGBForeColor (&kWhite);
- NumToString (frame, theString);
- MoveTo (10,470);
- DrawString (theString);
- NumToString (gShotsOnBoard, theString);
- MoveTo (10, 450);
- DrawString (theString);
- RGBForeColor (&kBlack);
- #endif
-
- /************* Draw all the sprites ***************/
-
- gEnemyShipGroup->DrawSpriteGroup ();
- gFriendlyShipGroup->DrawSpriteGroup ();
- gEnemyShotGroup->DrawSpriteGroup ();
- gFriendlyShotGroup->DrawSpriteGroup ();
-
-
- /************* Refresh the screen ***************/
-
- theErr = DSpContext_SwapBuffers( gDrawContext, NULL, NULL);
- #if qDebugging
- FAIL_OSERR (theErr,"\p Failed to swap the buffers.")
- #endif
-
-
- /************* Process Commands *************************************/
-
- // If we are syncing our timing, we'll make sure we have at least one command to process,
- // and then loop until all of the commands are completed. Otherwise we just grab one key
- // state and call through the loop once.
-
- #if qSyncTiming
- // Wait for a command to actually show up
- while (!theTimer.IsCommandWaiting())
- ;
-
- // Process all waiting commands.
- while (theTimer.RetrieveCommand (&gCommandKeys))
- #else
- theTimer.RetrieveCommand (&gCommandKeys);
- #endif
- {
- gFriendlyShipGroup->ProcessSpriteGroup();
- gEnemyShipGroup->ProcessSpriteGroup();
- gFriendlyShotGroup->ProcessSpriteGroup();
- gEnemyShotGroup->ProcessSpriteGroup();
-
- gFriendlyShotGroup->HitTest (gEnemyShipGroup);
- gEnemyShotGroup->HitTest (gFriendlyShipGroup);
-
- // Check for exit game
- if (CheckKey ((unsigned char *) &gCommandKeys, kExitGame))
- running = false;
-
- // Check for debugger break
- if (CheckKey ((unsigned char *) &gCommandKeys, kDebugger))
- {
- FlushEvents (everyEvent,0);
- Debugger();
- }
-
- #if qUsingSound
- // Give the sound API some time to service tasks.
- HY_ServiceTasks();
-
- // play some sounds.
- if (CheckKey ((unsigned char *) &gCommandKeys, kOne) && gPlayingSound)
- {
- HY_PlaySoundHandle (1, gSounds[0], NULL, 0, false);
- }
- if (CheckKey ((unsigned char *) &gCommandKeys, kTwo) && gPlayingSound)
- {
- HY_PlaySoundHandle (1, gSounds[1], NULL, 0, false);
- }
- if (CheckKey ((unsigned char *) &gCommandKeys, kThree) && gPlayingSound)
- {
- HY_PlaySoundHandle (1, gSounds[2], NULL, 0, false);
- }
- if (CheckKey ((unsigned char *) &gCommandKeys, kFour) && gPlayingSound)
- {
- HY_PlaySoundHandle (1, gSounds[3], NULL, 0, false);
- }
-
- // toggle the sound setting
- if (CheckKey ((unsigned char *) &gCommandKeys,kSoundToggle))
- {
- if (!soundKeyDown)
- {
- soundKeyDown = true;
- gPlayingSound = !gPlayingSound;
- if (!gPlayingSound)
- {
- HY_StopSample(1);
- HY_StopSample(2);
- HY_StopSample(3);
- HY_StopSample(4);
- }
- }
- }
- else
- {
- soundKeyDown = false;
- }
- #endif
- }
- }
-
-
- #if __profile__
- ProfilerSetStatus(false);
- ProfilerDump("\pMoofWarsDump");
- ProfilerTerm();
- #endif
-
- ShowCursor();
- // We want to flush all the keyboard events we haven't been taking.
- theTimer.AcceptCommands (false);
- FlushEvents(everyEvent, 0);
-
- return noErr;
- #if qDebugging
- error:
- return theErr;
- #endif
- }
-
- OSStatus CloseGame (void)
- {
- // This doesn't clean up everything just yet, but it should!
-
- if (gFriendlyShipGroup != NULL)
- {
- delete gFriendlyShipGroup;
- gFriendlyShipGroup = NULL;
- }
-
- if (gEnemyShipGroup != NULL)
- {
- delete gEnemyShipGroup;
- gEnemyShipGroup = NULL;
- }
-
- if (gFriendlyShotGroup != NULL)
- {
- delete gFriendlyShotGroup;
- gFriendlyShotGroup = NULL;
- }
-
- if (gEnemyShotGroup != NULL)
- {
- delete gEnemyShotGroup;
- gEnemyShotGroup = NULL;
- }
-
- if (theGrid != NULL)
- {
- delete theGrid;
- theGrid = NULL;
- }
-
- if (gShipGraphics != NULL)
- {
- gShipGraphics->DisposeReference;
- gShipGraphics = NULL;
- }
-
- if (gShotGraphics != NULL)
- {
- gShotGraphics->DisposeReference;
- gShotGraphics = NULL;
- }
-
- if (gDrawContext != NULL)
- {
- DSpContext_SetState (gDrawContext, kDSpContextState_Inactive);
- DSpContext_Release( gDrawContext);
- DSpShutdown();
- }
-
- if (gAppColorTable)
- DisposeCTable (gAppColorTable);
-
- return noErr;
- }
-
-
- Boolean CheckKey (unsigned char *PtrToKeyMap, short theKey)
- {
- unsigned char theByte, theBit;
- short byteIndex;
-
- byteIndex = theKey >> 3;
- theByte = *(unsigned char *)(PtrToKeyMap + byteIndex);
- theBit = 1L<<(theKey & 7);
-
- return (theByte & theBit);
- }
-